import { Inject, Injectable } from '@nestjs/common';
import Redis from 'ioredis';

@Injectable()
export class RedisService {
  constructor(
    @Inject('REDIS_CLIENT')
    public readonly redisClient: Redis,
  ) {}

  setValue(key: string, value: string) {
    return this.redisClient.set(key, value);
  }

  getValue(key: string) {
    return this.redisClient.get(key);
  }

  async hset({ key, value, expire = 60 * 30 }) {
    return await new Promise(async (resolve) => {
      // 1天
      await this.redisClient.set(key, JSON.stringify(value), 'EX', expire);
      resolve('OK');
    });
  }
  async hget(key) {
    return await new Promise(async (resolve) => {
      // 1天
      const data = await this.redisClient.get(key);
      if (data) {
        resolve(JSON.parse(data));
      } else {
        resolve(null);
      }
    });
  }

  async hdel(regKey) {
    const ips = [];

    await new Promise((resolve, reject) => {
      const stream = this.redisClient.scanStream({
        match: `${regKey}*`,
      });
      stream.on('data', (keys = []) => {
        stream.pause();
        if (keys.length) {
          const pipeline = this.redisClient.pipeline();
          keys.forEach(function (key) {
            // if (global.rediser.get(key) == value) {
            pipeline.del(key);
            // }
            ips.push(key.split('_')[1]);
          });
          pipeline
            .exec()
            .then(() => {
              stream.resume();
            })
            .catch((err) => {
              err.pattern = regKey;
              reject(err);
            });
        } else {
          resolve('NO_KEYS');
        }
      });
      stream.on('end', () => {
        resolve('OK');
      });
    });
    return ips;
  }

  async hkeys(key) {
    const ips = [];

    await new Promise((resolve) => {
      const stream = this.redisClient.scanStream({
        match: `${key}*`,
        count: 1000000,
      });
      stream.on('data', (keys = []) => {
        stream.pause();

        if (keys.length) {
          keys.forEach(function (key) {
            ips.push(key.split('_')[1]);
          });
          stream.resume();
        } else {
          resolve('NO_KEYS');
        }
      });
      stream.on('end', () => {
        resolve('OK');
      });
    });
    return ips;
  }

  async del(key) {
    return this.redisClient.del(key);
  }

  async blackList() {
    const users = await this.hkeys('black_');
    return users;
  }
  async addBlackList(ip) {
    await this.hset({
      key: 'black_' + ip,
      value: 1,
      expire: 86400,
    });
    return true;
  }

  async deleteBlack(ip = '') {
    const ips = await this.del('black_' + ip);
    return ips;
  }
}
